

#include "base/input_output_context.h"
#include "base_util.h"
#include "codec_config.h"
#include "dump.h"
#include "message_queue.h"
#include "operate_define.h"
#include "packet_frame_operate.h"
#include <cstdio>
#include <cstdlib>
#include <thread>


struct MessageQueue
{
	PacketMessageQueue m_packet_message;
	FrameMessageQueue  m_frame_message;
};


void ReadPacketData(InputFormatContext & input_format_ctx, MessageQueue & message_queue)
{
	AVPacket * packet = av_packet_alloc();
	ReadPacketDataToMessageQueue(&input_format_ctx, packet, message_queue.m_packet_message);
}

int main(int argc, const char * argv[])
{
	if (argc < 2)
	{
		PrintLog("need input filename param");
		return EXIT_FAILURE;
	}
	std::string filename = argv[1];
	InputFormatContext input_format_ctx;
	bool result = input_format_ctx.OpenUrlWithFindStreamInfo(filename);
	if (result)
	{
		CodecConfig codec_config;

		codec_config.m_video_config.m_codec_name = "";
		codec_config.m_video_config.m_hw_name    = "qsv";

		result = input_format_ctx.CreateVideoDecoderCtx("", codec_config);
		if (!result)
		{
			PrintLog("create video decoder ctx failed");
		}
		else
		{
			result = input_format_ctx.CreateAudioDecoderCtx("", CodecConfig{});
			if (!result)
			{
				PrintLog("create audio decoder ctx failed");
			}
			else
			{
				PrintLog("init decoder ctx success");
			}	
		}
	}
	if (!result)
	{
		return EXIT_FAILURE;
	}

	MessageQueue message_queue;
	message_queue.m_packet_message.InitMessageQueue(100);
	message_queue.m_frame_message.InitMessageQueue(100);

	std::thread thd = std::thread([&message_queue, &input_format_ctx](){

		ReadPacketData(input_format_ctx, message_queue);

	});
	ProcessPacketDataFromMessageQueue(message_queue.m_packet_message, [&input_format_ctx, &message_queue](AVPacket * packet){

		auto media_stream = input_format_ctx.MediaStreamIndex(packet->stream_index);
		if (media_stream->AvStream()->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
		{
			DecodePacketDataToMessageQueue(input_format_ctx.VideoDecoder(), packet, message_queue.m_frame_message);
			ProcessFrameDataFromMessageQueue(message_queue.m_frame_message, [&input_format_ctx](AVFrame * frame){


				PrintFrameInfo(input_format_ctx.VideoDecoder()->AvCodecCtx(), frame);
				// printf("vidoe pts : %8ld\tdts : %8ld\tduration : %8ld.\n", frame->pts, frame->pkt_dts, frame->pkt_duration);

			}, false);
		}
		else if (media_stream->AvStream()->codecpar->codec_type == AVMEDIA_TYPE_AUDIO)
		{
			DecodePacketDataToMessageQueue(input_format_ctx.AudioDecoder(), packet, message_queue.m_frame_message);
			ProcessFrameDataFromMessageQueue(message_queue.m_frame_message, [&input_format_ctx](AVFrame * frame){


				PrintFrameInfo(input_format_ctx.AudioDecoder()->AvCodecCtx(), frame);
				// printf("audio pts : %8ld\tdts : %8ld\tduration : %8ld.\n", frame->pts, frame->pkt_dts, frame->pkt_duration);

			}, false);
		}
	}, true);
	if (thd.joinable())
	{
		thd.join();
	}
	return EXIT_SUCCESS;
}